/*
 *  cashregister.c
 *  
 *
 *  Created by Rayvionne French on 7/22/11.
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */
#include "syscall.h"

#define MAXCLERKS 5
#define MAXSTOCKBOYS 10
#define MAXAISLES 5
#define MAXSHELVES 10
#define MAXSHELFQUANTITY 3
#define MAXCARTSIZE 10
#define SHELVESPERAISLE 2

int globalLock;

/* Customer data */
int customerCount;
int clerkCount;
int cashRegisterCount;
int stockboyCount;

/* To keep track of total customers served */
int totalCustomersServed;
/* The actual store total, not the manager's estimate */
int storeTotal;

/* Home depot's lock for each shelf */
int shelfLocks[MAXSHELVES];
/* Home depot's Shelves */

int shelfState;
int shelfAisle;
int shelfItem;
int shelfQuantity;

/* Represents the line length for each clerk (each index) */
int clerkLineLengths;
/* Clerk line lock ensures that only one instance can check/increment/decrement the line count at a time.*/
int clerkLineLock;
/* For customers waiting in lines */
int clerkLineCV[MAXCLERKS];

/* Lock that protects the checkoutAssistance button */
int checkoutAssistanceLock;
/* Button that is pushed when a customer sees that all clerks are ONBREAK.
 * 1 is need help, 0 if no help needed */
int checkoutAssistance;
/* ConditionVar that will wake up customers when the checkout assistance request
 * has been fulfilled */
int checkoutAssistanceCV;

/* The customer must have a way to know whether the clerk
 * is on break; 0 is working, 1 is on break.*/
int clerkStates;
int clerkLocks[MAXCLERKS];
int clerkCV[MAXCLERKS];

int clerkAssistanceButton;
int clerkAssistanceButtonLock;

/* Lock for knowing which customer are currently being served - by clerk */
int customersAtCheckoutLocks[MAXCLERKS];
int customersAtCheckout;

int refundingTransaction;
int paymentDue;
int amountPaid;
int lastItemGiven;
int itemToScan;

int cashRegisterFinishedStatus; 
int cashRegisterSales;
int cashRegisterAmount;
int cashRegisterLocks[MAXCLERKS];
int cashRegisterCV[MAXCLERKS];

int cashRegisterAssistance;
int cashRegisterAssistanceCV[MAXCLERKS];
int cashRegisterAssistanceLock;
int cashRegisterRequest;

/* Lock for changing aisle location of a stockboy */
int stockboyStatusLock;
/* for current aisle location, -1 means currently not in any aisle */
int stockboyStatus; 

/* Lock for the stockroom */
int stockroomLineLock;
int stockroomLineCV;
int stockroomLineLength;

int stockroomLock;
int stockboyInStockroom;

/* Lock for stockboys */
int stockboyLocks[MAXSTOCKBOYS];
/* State of a stockboy: 0 is working, 1 is on break */
int stockboyStates;
/* Condition variable for a stockboy */
int stockboysCV[MAXSTOCKBOYS];

int stockboyReadyLock[MAXAISLES];
int aisleHelpLine;
int aisleHelpLocks[MAXAISLES];
int aisleCV[MAXAISLES];

int customerWithStockboyLock[MAXSTOCKBOYS];
int customerWithStockboy;
int stockboyItemToHelp;
int shelfNumberForCustomer;
int aisleNumberForCustomer;

/* Lock for customer & manager to access this button */
int customerAssistanceButtonLock;
/* Customer presses on this button if no stockboys can be found */
int customerAssistanceButton;
/* CV for customers to wait on when the manager wakes up all stockboys */
int customerAssistanceButtonCV;
 
 
 
/* Takes in a char array and returns the length of the char array. */
int charCount(char* ch)
{	
	char toString[3];
	int count = 0;
	int i=0;
	while(ch[i] != '\n')
	{
		count++;
		i++;
	}
	return count+1;
}

void CreateMonitorsLocksCVs() {
	
	/* Lock for all global data */
	globalLock = CreateLock("globalLock", 10);
	
	/* Trackers for the number of each entity in simulation */
	customerCount = CreateIntMV("customerCount MV" , charCount("customerCount MV\n")-1, 1);
	clerkCount = CreateIntMV("clerkCount MV" , charCount("clerkCount MV\n")-1, 1);
	cashRegisterCount = CreateIntMV("cashRegisterCount MV" , charCount("cashRegisterCount MV\n")-1, 1);
	stockboyCount = CreateIntMV("stockboyCount MV" , charCount("stockboyCount MV\n")-1, 1);

	/* To keep track of total customers served */
	totalCustomersServed = CreateIntMV("totalCstmrsServed MV" , charCount("totalCstmrsServed MV\n")-1, 1);
	/* The actual store total, not the manager's estimate */
	storeTotal = CreateIntMV("storeTotal MV" , charCount("storeTotal MV\n")-1, 1);
	
	checkoutAssistance = CreateIntMV("checkoutHelp MV" , charCount("checkoutHelp MV\n")-1, 1);
	checkoutAssistanceLock = CreateLock("checkoutHelpLock", charCount("checkoutHelpLock\n")-1);
	checkoutAssistanceCV = CreateCV("checkoutHelpCV", charCount("checkoutHelpCV\n")-1);
	
	/* CLERK LINE MONITOR */
	clerkLineLengths = CreateIntMV("clerkLineLengths MV" , charCount("clerkLineLengths MV\n")-1, MAXCLERKS);
	clerkLineLock = CreateLock("clerkLineLock", 13);
	clerkLineCV[0] = CreateCV("clerkLineCV0", 12);
	clerkLineCV[1] = CreateCV("clerkLineCV1", 12);
	clerkLineCV[2] = CreateCV("clerkLineCV2", 12);
	clerkLineCV[3] = CreateCV("clerkLineCV3", 12);
	clerkLineCV[4] = CreateCV("clerkLineCV4", 12);
	
	/* CLERK MONITOR */
	clerkStates = CreateIntMV("clerkStates MV" , charCount("clerkStates MV\n")-1, MAXCLERKS);
	clerkLocks[0] = CreateLock("clerkLock0", 10);
	clerkLocks[1] = CreateLock("clerkLock1", 10);
	clerkLocks[2] = CreateLock("clerkLock2", 10);
	clerkLocks[3] = CreateLock("clerkLock3", 10);
	clerkLocks[4] = CreateLock("clerkLock4", 10);
	clerkCV[0] = CreateCV("clerkCV0", 8); 
	clerkCV[1] = CreateCV("clerkCV1", 8);
	clerkCV[2] = CreateCV("clerkCV2", 8);
	clerkCV[3] = CreateCV("clerkCV3", 8);
	clerkCV[4] = CreateCV("clerkCV4", 8);

	/* CLERK ASSISTANCE MONITOR */
	clerkAssistanceButton = CreateIntMV("clerkHelpBtn MV" , charCount("clerkHelpBtn MV\n")-1, 1);
	clerkAssistanceButtonLock = CreateLock("clerkHelpBttn", 21);

	/* CHECKOUT SHARED DATA MONITOR */
	customersAtCheckout = CreateIntMV("cstmrsAtChckt MV" , charCount("cstmrsAtChckt MV\n")-1, MAXCLERKS);
	refundingTransaction = CreateIntMV("rfndngTrnsctn MV" , charCount("rfndngTrnsctn MV\n")-1, MAXCLERKS);
	paymentDue = CreateIntMV("paymentDue MV" , charCount("paymentDue MV\n")-1, MAXCLERKS);
	amountPaid = CreateIntMV("amountPaid MV" , charCount("amountPaid MV\n")-1, MAXCLERKS);
	lastItemGiven = CreateIntMV("lastItemGiven MV" , charCount("lastItemGiven MV\n")-1, MAXCLERKS);
	itemToScan = CreateIntMV("itemToScan MV" , charCount("itemToScan MV\n")-1, MAXCLERKS);
	customersAtCheckoutLocks[0] = CreateLock("cstmrsAtChcktLck0", charCount("cstmrsAtChcktLck0\n")-1);
	customersAtCheckoutLocks[1] = CreateLock("cstmrsAtChcktLck1", charCount("cstmrsAtChcktLck1\n")-1);
	customersAtCheckoutLocks[2] = CreateLock("cstmrsAtChcktLck2", charCount("cstmrsAtChcktLck2\n")-1);
	customersAtCheckoutLocks[3] = CreateLock("cstmrsAtChcktLck3", charCount("cstmrsAtChcktLck3\n")-1);
	customersAtCheckoutLocks[4] = CreateLock("cstmrsAtChcktLck4", charCount("cstmrsAtChcktLck4\n")-1);

	/* CASH REGISTER MONITOR */
	cashRegisterFinishedStatus = CreateIntMV("cshRgstrFnshdStts MV" , charCount("cshRgstrFnshdStts MV\n")-1, MAXCLERKS);
	cashRegisterSales = CreateIntMV("cashRegisterSales MV" , charCount("cashRegisterSales MV\n")-1, MAXCLERKS);
	cashRegisterAmount = CreateIntMV("cshRgstrAmnt MV" , charCount("cshRgstrAmnt MV\n")-1, MAXCLERKS);
	cashRegisterLocks[0] = CreateLock("registerLock0", 13);
	cashRegisterLocks[1] = CreateLock("registerLock1", 13);
	cashRegisterLocks[2] = CreateLock("registerLock2", 13);
	cashRegisterLocks[3] = CreateLock("registerLock3", 13);
	cashRegisterLocks[4] = CreateLock("registerLock4", 13);
	cashRegisterCV[0] = CreateCV("registerCV0", 11);
	cashRegisterCV[1] = CreateCV("registerCV1", 11);
	cashRegisterCV[2] = CreateCV("registerCV2", 11);
	cashRegisterCV[3] = CreateCV("registerCV3", 11);
	cashRegisterCV[4] = CreateCV("registerCV4", 11);

	/* CASH REGISTER ASSISTANCE MONITOR */
	cashRegisterAssistance = CreateIntMV("cshRgstrAssstnc MV" , charCount("cshRgstrAssstnc MV\n")-1, MAXCLERKS);
	cashRegisterRequest = CreateIntMV("cshRgstrRqst MV" , charCount("cshRgstrRqst MV\n")-1, MAXCLERKS);
	cashRegisterAssistanceLock = CreateLock("cashRegAssistLock", charCount("cashRegAssistLock\n")-1); 
	cashRegisterAssistanceCV[0] = CreateCV("cashReg0AssistCV", charCount("cashReg_AssistCV\n")-1);
	cashRegisterAssistanceCV[1] = CreateCV("cashReg1AssistCV", charCount("cashReg_AssistCV\n")-1);
	cashRegisterAssistanceCV[2] = CreateCV("cashReg2AssistCV", charCount("cashReg_AssistCV\n")-1);
	cashRegisterAssistanceCV[3] = CreateCV("cashReg3AssistCV", charCount("cashReg_AssistCV\n")-1);
	cashRegisterAssistanceCV[4] = CreateCV("cashReg4AssistCV", charCount("cashReg_AssistCV\n")-1);
	
	/* STOCKBOY STATUS MONITOR */
	stockboyStatus = CreateIntMV("stockboyStatus MV" , charCount("stockboyStatus MV\n")-1, MAXSTOCKBOYS);
	stockboyStatusLock = CreateLock("stockboyStatusLock", charCount("stockboyStatusLock\n")-1);
	
	/* STOCKBOY MONITOR */
	stockboyStates =  CreateIntMV("stockboyStates MV" , charCount("stockboyStates MV\n")-1, MAXSTOCKBOYS);
	stockboyLocks[0] = CreateLock("stockboy0lock", charCount("stockboy0lock\n")-1);
	stockboyLocks[1] = CreateLock("stockboy1lock", charCount("stockboy1lock\n")-1);
	stockboyLocks[2] = CreateLock("stockboy2lock", charCount("stockboy2lock\n")-1);
	stockboyLocks[3] = CreateLock("stockboy3lock", charCount("stockboy3lock\n")-1);
	stockboyLocks[4] = CreateLock("stockboy4lock", charCount("stockboy4lock\n")-1);
	stockboyLocks[5] = CreateLock("stockboy5lock", charCount("stockboy5lock\n")-1);
	stockboyLocks[6] = CreateLock("stockboy6lock", charCount("stockboy6lock\n")-1);
	stockboyLocks[7] = CreateLock("stockboy7lock", charCount("stockboy7lock\n")-1);
	stockboyLocks[8] = CreateLock("stockboy8lock", charCount("stockboy8lock\n")-1);
	stockboyLocks[9] = CreateLock("stockboy9lock", charCount("stockboy9lock\n")-1);
	stockboysCV[0] = CreateCV("stockboy0CV", charCount("stockboy0CV\n")-1);
	stockboysCV[1] = CreateCV("stockboy1CV", charCount("stockboy1CV\n")-1);
	stockboysCV[2] = CreateCV("stockboy2CV", charCount("stockboy2CV\n")-1);
	stockboysCV[3] = CreateCV("stockboy3CV", charCount("stockboy3CV\n")-1);
	stockboysCV[4] = CreateCV("stockboy4CV", charCount("stockboy4CV\n")-1);
	stockboysCV[5] = CreateCV("stockboy5CV", charCount("stockboy5CV\n")-1);
	stockboysCV[6] = CreateCV("stockboy6CV", charCount("stockboy6CV\n")-1);
	stockboysCV[7] = CreateCV("stockboy7CV", charCount("stockboy7CV\n")-1);
	stockboysCV[8] = CreateCV("stockboy8CV", charCount("stockboy8CV\n")-1);
	stockboysCV[9] = CreateCV("stockboy9CV", charCount("stockboy9CV\n")-1);
	
	/* CUSTOMER-STOCKBOY SHARED DATA MONITOR*/
	customerWithStockboy = CreateIntMV("cstmrWithSB_MV" , charCount("cstmrWithSB_MV\n")-1, MAXSTOCKBOYS);
	stockboyItemToHelp = CreateIntMV("sbItemToHelpMV" , charCount("sbItemToHelpMV\n")-1, MAXSTOCKBOYS);
	shelfNumberForCustomer = CreateIntMV("shelfNum4CstmrMV" , charCount("shelfNum4CstmrMV\n")-1, MAXSTOCKBOYS);
	aisleNumberForCustomer = CreateIntMV("aisleNum4CstmrMV" , charCount("aisleNum4CstmrMV\n")-1, MAXSTOCKBOYS);
	customerWithStockboyLock[0] = CreateLock("cstmrWithSB0Lock", charCount("cstmrWithSB0Lock\n")-1);
	customerWithStockboyLock[1] = CreateLock("cstmrWithSB1Lock", charCount("cstmrWithSB1Lock\n")-1);
	customerWithStockboyLock[2] = CreateLock("cstmrWithSB2Lock", charCount("cstmrWithSB2Lock\n")-1);
	customerWithStockboyLock[3] = CreateLock("cstmrWithSB3Lock", charCount("cstmrWithSB3Lock\n")-1);
	customerWithStockboyLock[4] = CreateLock("cstmrWithSB4Lock", charCount("cstmrWithSB4Lock\n")-1);
	customerWithStockboyLock[5] = CreateLock("cstmrWithSB5Lock", charCount("cstmrWithSB5Lock\n")-1);
	customerWithStockboyLock[6] = CreateLock("cstmrWithSB6Lock", charCount("cstmrWithSB6Lock\n")-1);
	customerWithStockboyLock[7] = CreateLock("cstmrWithSB7Lock", charCount("cstmrWithSB7Lock\n")-1);
	customerWithStockboyLock[8] = CreateLock("cstmrWithSB8Lock", charCount("cstmrWithSB8Lock\n")-1);
	customerWithStockboyLock[9] = CreateLock("cstmrWithSB9Lock", charCount("cstmrWithSB9Lock\n")-1);
	
	/* AISLE HELP MONITOR */
	aisleHelpLine = CreateIntMV("aisleHelpLine MV" , charCount("aisleHelpLine MV\n")-1, MAXAISLES);
	stockboyReadyLock[0] = CreateLock("sbReady0Lock", charCount("sbReady0Lock\n")-1);
	stockboyReadyLock[1] = CreateLock("sbReady1Lock", charCount("sbReady1Lock\n")-1);
	stockboyReadyLock[2] = CreateLock("sbReady2Lock", charCount("sbReady2Lock\n")-1);
	stockboyReadyLock[3] = CreateLock("sbReady3Lock", charCount("sbReady3Lock\n")-1);
	stockboyReadyLock[4] = CreateLock("sbReady4Lock", charCount("sbReady4Lock\n")-1);
	aisleHelpLocks[0] = CreateLock("aisle0Lock", 10);
	aisleHelpLocks[1] = CreateLock("aisle1Lock", 10);
	aisleHelpLocks[2] = CreateLock("aisle2Lock", 10);
	aisleHelpLocks[3] = CreateLock("aisle3Lock", 10);
	aisleHelpLocks[4] = CreateLock("aisle4Lock", 10);
	aisleCV[0] = CreateCV("aisle0CV", 8);
	aisleCV[1] = CreateCV("aisle1CV", 8);
	aisleCV[2] = CreateCV("aisle2CV", 8);
	aisleCV[3] = CreateCV("aisle3CV", 8);
	aisleCV[4] = CreateCV("aisle4CV", 8);
	
	/* CUSTOMER ASSISTANCE MONITRO */
	customerAssistanceButton = CreateIntMV("cstmrAssistBttnMV" , charCount("cstmrAssistBttnMV\n")-1, 1);
	customerAssistanceButtonLock = CreateLock("cstmrAssistBttnLock", charCount("cstmrAssistBttnLock\n")-1);
	customerAssistanceButtonCV = CreateCV("cstmrAssistBttnCV", charCount("cstmrAssistBttnLock\n")-1);
	
	/* STOCK ROOM LINE MONITOR */
	stockroomLineLength =  CreateIntMV("stkroomLineMV" , charCount("stkroomLineMV\n")-1, 1);
	stockboyInStockroom = CreateIntMV("sbInStockroomMV" , charCount("sbInStockroomMV\n")-1, 1);
	stockroomLineLock = CreateLock("stkroomLineLock", charCount("stockroomLineLock\n")-1);
	stockroomLineCV = CreateCV("stockroomCV", charCount("stkroomCV")-1);
	
	/* STOCK ROOM MONITOR */
	stockroomLock = CreateLock("stockroomLock", charCount("stockroomLock\n")-1);
	
	/* SHELF MONITOR */
	shelfState = CreateIntMV("shelfStateMV" , charCount("shelfStateMV\n")-1, MAXSHELVES);
	shelfAisle = CreateIntMV("shelfAisleMV" , charCount("shelfAisleMV\n")-1, MAXSHELVES);
	shelfItem = CreateIntMV("shelfItemMV" , charCount("shelfItemMV\n")-1, MAXSHELVES);
	shelfQuantity = CreateIntMV("shelfQuantityMV" , charCount("shelfQuantityMV\n")-1, MAXSHELVES);
	shelfLocks[0] = CreateLock("shelfLock0", 10);
	shelfLocks[1] = CreateLock("shelfLock1", 10);
	shelfLocks[2] = CreateLock("shelfLock2", 10);
	shelfLocks[3] = CreateLock("shelfLock3", 10);
	shelfLocks[4] = CreateLock("shelfLock4", 10);
	shelfLocks[5] = CreateLock("shelfLock5", 10);
	shelfLocks[6] = CreateLock("shelfLock6", 10);
	shelfLocks[7] = CreateLock("shelfLock7", 10);
	shelfLocks[8] = CreateLock("shelfLock8", 10);
	shelfLocks[9] = CreateLock("shelfLock9", 10);
}	
	
	
void Initialize() {
	int j, m;
	
	AlterIntMV(customerCount, 0, 0);
	AlterIntMV(clerkCount, 0, 0);
	AlterIntMV(cashRegisterCount, 0, 0);
	AlterIntMV(stockboyCount, 0, 0);

	AlterIntMV(totalCustomersServed, 0, 0); 
	AlterIntMV(storeTotal, 0, 0);
	
	AlterIntMV(checkoutAssistance, 0, 0);
	AlterIntMV(clerkAssistanceButton, 0, 0);
	AlterIntMV(cashRegisterFinishedStatus, 0, 0);
	AlterIntMV(customerAssistanceButton, 0, 0);
	
	AlterIntMV(stockroomLineLength, 0, 0);
	AlterIntMV(stockboyInStockroom, 0, -1);
	
	for(j=0; j<MAXCLERKS; j++) {
		AlterIntMV(clerkLineLengths, j, 0);
		AlterIntMV(clerkStates, j, 1);
		AlterIntMV(paymentDue, j, 0);
		AlterIntMV(lastItemGiven, j, 0);
		AlterIntMV(itemToScan, j, -1);
		AlterIntMV(cashRegisterFinishedStatus, j, 0);
		AlterIntMV(customersAtCheckout, j, -1);
		AlterIntMV(cashRegisterSales, j, 0);
		AlterIntMV(cashRegisterAmount, j, 0);
		AlterIntMV(cashRegisterAssistance, j, 0);
		AlterIntMV(cashRegisterRequest, j, 0);
		AlterIntMV(refundingTransaction, j, 0);
	}
	
	m=0;
	for(j=0; j < MAXSHELVES; j++) {
		AlterIntMV(shelfState , j, 0);
		AlterIntMV(shelfAisle, j, m);
		AlterIntMV(shelfItem, j, j);
		AlterIntMV(shelfQuantity, j, MAXSHELFQUANTITY);
	
		if(j == 1 || j == 3 || j == 5 || j == 7)
			m++;
	}
	
	for(j=0; j < MAXSTOCKBOYS; j++) {
		AlterIntMV(stockboyStatus, j, -1);
		AlterIntMV(stockboyStates, j, 1);
		AlterIntMV(stockboyItemToHelp, j, -1);
		AlterIntMV(shelfNumberForCustomer, j, -1);
		AlterIntMV(aisleNumberForCustomer, j, -1);
		AlterIntMV(customerWithStockboy, j, -1);
		AlterIntMV(stockboyItemToHelp, j, -1);
	}
	
	for(j=0; j < MAXAISLES; j++) {
		AlterIntMV(aisleHelpLine, j, 0);
	}
	
}

void CashRegister_checkScanner(int id)
{
	int sizes[2];
	int inputs[3];
	int currentAmountDue = 0;
	int totalProducts = 0;
	
	while(1)
	{	
		currentAmountDue += 1;
		totalProducts++;
		/*SWrite("Cash Register [%d] scanned item [%d].\n", charCount("Cash Register [%d] scanned item [%d].\n"),
			id, itemToScan[id]);*/
		if(RetrieveIntMV(cashRegisterFinishedStatus, id) == 1)
		{
			AlterIntMV(paymentDue, id, currentAmountDue);
			AlterIntMV(cashRegisterFinishedStatus, id,  0);
			sizes[0] = charCount("Cash Register [%d] scanned all [%d] items for Customer [%d].\n");
			sizes[1] = 3;
			inputs[0] = id;
			inputs[1] = totalProducts;
			inputs[2]  = RetrieveIntMV(customersAtCheckout, id);
			WriteAll("Cash Register [%d] scanned all [%d] items for Customer [%d].\n", sizes, inputs);
			CVSignal(cashRegisterCV[id], cashRegisterLocks[id]);
			CVWait(cashRegisterCV[id], cashRegisterLocks[id]);
			break;
		}
		CVSignal(cashRegisterCV[id], cashRegisterLocks[id]);
		CVWait(cashRegisterCV[id], cashRegisterLocks[id]);
	}
	
	
}

void CashRegister() {
	int k;
	int id;
	int totalCash = 0;
	int currentAmountDue = 0;
	int sizes[2];
	int inputs[4];
	
	Write("Starting Cash Register\n", 23, ConsoleOutput);
	LockAcquire(globalLock);
	id = RetrieveIntMV(cashRegisterCount, 0);
	AlterIntMV(cashRegisterCount,0, RetrieveIntMV(cashRegisterCount, 0)+1);
	SWrite("[%d] cash registers in store.\n", charCount("[%d] cash registers in store.\n"), RetrieveIntMV(cashRegisterCount, 0), 0);
	LockAcquire(cashRegisterLocks[id]);
	LockRelease(globalLock);
	
	sizes[1] = 4;
	inputs[0] = id;
	
	while(1) {
	
		CVWait(cashRegisterCV[id], cashRegisterLocks[id]);
		
		CashRegister_checkScanner(id);
		/* cash register has scanned everything */
		
		sizes[0] = charCount("Cash Register [%d] gave total cost $[%d] for Customer[%d] to Clerk[%d] for items.\n");
		inputs[1]  = RetrieveIntMV(paymentDue, id);
		inputs[2]  = RetrieveIntMV(customersAtCheckout, id);
		inputs[3] = id;
		WriteAll("Cash Register [%d] gave total cost $[%d] for Customer[%d] to Clerk[%d] for items.\n", 
			sizes, inputs);
		
			
		if(RetrieveIntMV(refundingTransaction, id) == 0) {
			CVSignal(cashRegisterCV[id], cashRegisterLocks[id]);
			CVWait(cashRegisterCV[id], cashRegisterLocks[id]);
			LockAcquire(globalLock);
			AlterIntMV(storeTotal, 0, RetrieveIntMV(storeTotal, 0) + RetrieveIntMV(amountPaid, id));
			AlterIntMV(cashRegisterSales, id, RetrieveIntMV(cashRegisterSales, id)+ RetrieveIntMV(amountPaid, id));
			AlterIntMV(cashRegisterAmount, id, RetrieveIntMV(cashRegisterAmount, id) + RetrieveIntMV(amountPaid, id));
			LockRelease(globalLock);

			SWrite("Cash Register [%d] got the money from Clerk [%d].\n",
				charCount("Cash Register [%d] got the money from Clerk [%d].\n"), id, id);
		}
		else {
			LockAcquire(globalLock);
			
			if((RetrieveIntMV(cashRegisterAmount,id) - RetrieveIntMV(paymentDue,id)) < 0) {
				LockRelease(globalLock);
				LockAcquire(cashRegisterAssistanceLock);
				AlterIntMV(cashRegisterAssistance, id, 1);
				AlterIntMV(cashRegisterRequest, id,  RetrieveIntMV(paymentDue, id));
				SWrite("Cash Register [%d] informed the manager that he needs $[%d].\n",
					charCount("Cash Register [%d] informed the manager that he needs $[%d].\n"), id, RetrieveIntMV(paymentDue, id));
				CVWait(cashRegisterAssistanceCV[id], cashRegisterAssistanceLock);
				LockRelease(cashRegisterAssistanceLock);
				LockAcquire(globalLock);
			}
			AlterIntMV(cashRegisterAmount, id, RetrieveIntMV(cashRegisterAmount,id) - RetrieveIntMV(paymentDue, id));
			LockRelease(globalLock);
			
			SWrite("Cash Register [%d] gave the money to Clerk [%d].\n",
				charCount("Cash Register [%d] gave the money to Clerk [%d].\n"), id, id);
			CVSignal(cashRegisterCV[id], cashRegisterLocks[id]);
			CVWait(cashRegisterCV[id], cashRegisterLocks[id]);	
		}
		
		sizes[0] = charCount("Cash Register [%d] gave receipt to Clerk [%d] for Customer[%d].\n");
		sizes[1] = 3;
		inputs[1] = id;
		inputs[2]  = RetrieveIntMV(customersAtCheckout, id);
		WriteAll("Cash Register [%d] gave receipt to Clerk [%d] for Customer[%d].\n", sizes, inputs);
		
		if(RetrieveIntMV(refundingTransaction,id) == 0) {
			SWrite("Cash Register [%d] total sale is $[%d].\n",
				charCount("Cash Register [%d] total sale is $[%d].\n"), id, RetrieveIntMV(paymentDue, id));
		}
		else {
			SWrite("Cash Register [%d] total sale is $[%d].\n",
				charCount("Cash Register [%d] total sale is $[%d].\n"), id, (RetrieveIntMV(paymentDue, id)*-1));
		}
			
		CVSignal(cashRegisterCV[id], cashRegisterLocks[id]);
	}
	LockRelease(cashRegisterLocks[id]);
	
	Exit(-1);
}

int main() {
	int i;
	
	CreateMonitorsLocksCVs();
	Initialize();
	
	for(i = 0 ; i < 5 ; i++) {
		Fork(&CashRegister, "CashRegister", 13);
	}
}